package hehe.validation.validator;

import hehe.validation.base.ValidateResult;
import hehe.validation.util.ValidatorUtil;
import java.util.HashMap;
import java.util.Map;

/**
 * 验证器基类
 *<B>说明：</B>
 *<pre>
 * 略
 *</pre>
 *<B>示例：</B>
 *<pre>
 *  略
 *</pre>
 *<B>日志：</B>
 *<pre>
 *  略
 *</pre>
 *<B>注意事项：</B>
 *<pre>
 *  略
 *</pre>
 */
abstract public class Validator
{
    public static String packageName;

    /**
     * 错误提示信息
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected String tip = "";

    /**
     * 当验证值为空时是否调用验证
     *<B>说明：</B>
     *<pre>
     *  true 表示　值为空时,不验证,false 表示值为空，继续验证
     *</pre>
     */
    protected boolean onEmpty = false;

    /**
     * 结果是否非
     *<B>说明：</B>
     *<pre>
     *  true 表示取非结果
     *</pre>
     */
    protected boolean non = false;

    /**
     * 消息模板替换参数
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected Map<String,Object> messageParams = new HashMap<>();

    public Validator(){}

    public Validator(Map<String,Object> attrs)
    {
        ValidatorUtil.setAttrs(this,attrs);
    }

    /**
     * 获取当前类包名
     *<B>说明：</B>
     *<pre>
     * 　略
     *</pre>
     * @return 当前包名
     */
    public static String getPackageName()
    {
        if (packageName != null) {
            return packageName;
        }

        packageName = new Object()    {
            public String getPackageName()
            {
                return  this.getClass().getPackage().getName();
            }
        }.getPackageName();

        return packageName;
    }

    /**
     * 设置提示消息替换参数
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected void putMessageParams(String key,Object value)
    {
        this.messageParams.put(key,value);
    }

    /**
     * 是否跳过验证
     *<B>说明：</B>
     *<pre>
     *　略
     *</pre>
     * @return boolean
     */
    protected boolean isSkip(Object value)
    {
        // 验证是否空跳过
        if (!this.onEmpty && this.isEmpty(value)) {
            return true;
        }

        return false;
    }

    /**
     * 判断指定的值是否为空
     *<B>说明：</B>
     *<pre>
     *　略
     *</pre>
     * @param value　验证值
     * @return boolean true 表示为空,否则为false
     */
    protected boolean isEmpty(Object value)
    {
        if (value == null) {
            return true;
        }

        return false;
    }

    /**
     * 验证方法接口
     *<B>说明：</B>
     *<pre>
     *　子类必须实现此方法
     *</pre>
     * @param  value
     * @return boolean
     */
    public boolean validate(Object value)
    {
        return this.validate(value,null);
    }

    /**
     * 验证方法接口
     *<B>说明：</B>
     *<pre>
     *　子类必须实现此方法
     *</pre>
     * @param  value 验证值
     * @param  name　验证属性名称
     * @return boolean
     */
    public boolean validate(Object value,String name)
    {
        if (this.isSkip(value)) {
            return true;
        }

        boolean result = this.validateValue(value);
        if (this.non == true) {
            result = !result;
        }

        return result;
    }

    /**
     * 验证方法接口
     *<B>说明：</B>
     *<pre>
     *　子类必须实现此方法
     *</pre>
     * @param  value
     * @return boolean
     */
    abstract protected boolean validateValue(Object value);

    /**
     * 获取消息提示
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     */
    protected String getMessage()
    {
        String msg = "";
        msg = this.formatMessage(this.tip,this.messageParams);

        return msg;
    }

    /**
     * 消息格式化
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     * @param message 消息模板
     * @param params 消息模板替换参数
     */
    protected String formatMessage(String message,Map<String,Object> params)
    {
        String msg = message;
        for (Map.Entry<String, Object> param : params.entrySet()) {
            msg = msg.replaceAll("\\{" + param.getKey() + "\\}",param.getValue().toString());
        }

        return msg;
    }

    /**
     * 批量验证
     *<B>说明：</B>
     *<pre>
     *  略
     *</pre>
     *
     */
    public ValidateResult validateValues(Map<String,Object> values)
    {
        boolean result = true;
        for (Map.Entry<String,Object> value : values.entrySet()) {
            if (!this.validate(value.getValue(),value.getKey())) {
                result = false;
            }
        }

        if (result == false) {
            return new ValidateResult(false,this.getMessage());
        } else {
            return new ValidateResult(true);
        }
    }
}
